from ctypes import *
from enum import Enum
from typing import List

from arcface import lib_func


# 激活文件信息
class ASF_ActiveFileInfo(Structure):
    _fields_ = [('startTime', c_char_p),  # SDK开始时间
                ('endTime', c_char_p),  # SDK截止时间
                ('activeKey', c_char_p),  # 激活码
                ('platform', c_char_p),  # 平台版本
                ('sdkType', c_char_p),  # SDK 类型
                ('appId', c_char_p),  # APPID
                ('sdkKey', c_char_p),  # SDKKEY
                ('sdkVersion', c_char_p),  # SDK 版本号
                ('fileVersion', c_char_p)  # 激活文件版本号
                ]


# 人脸框 信息
class MRECT(Structure):
    _fields_ = [('left', c_int32),
                ('top', c_int32),
                ('right', c_int32),
                ('bottom', c_int32)]


# 单人脸信息
class ASF_SingleFaceInfo(Structure):
    _fields_ = [('faceRect', MRECT),  # 人脸框
                ('faceOrient', c_int32)  # 人脸角度
                ]


# 多人脸信息
class ASF_MultiFaceInfo(Structure):
    _fields_ = [('faceRect', POINTER(MRECT)),  # 人脸框数组
                ('faceOrient', POINTER(c_int32)),  # 人脸角度数组
                ('faceNum', c_int32),  # 检测到的人脸个数
                ('faceID', POINTER(c_int32))  # 在 一张人脸从进入画面直到离开画面，faceID不变。在VIDEO模式下有效，IMAGE模式下为空
                ]


# 人脸特征信息
class ASF_FaceFeature(Structure):
    _fields_ = [('feature', c_void_p),  # 人脸特征
                ('featureSize', c_int32)  # 人脸特征长度
                ]

    def set_feature(self, feature: bytes, featureSize=1032):
        """
        设置 特征值对象
        :param feature: 对象的二进制内容
        :param featureSize: 二进制长度
        :return: None
        """
        self.featureSize = featureSize
        self.feature = lib_func.dllc.malloc(featureSize)
        lib_func.dllc.memcpy(self.feature, feature, featureSize)

    def get_feature_bytes(self):
        return string_at(self.feature, self.featureSize)


# 年龄信息
class ASF_AgeInfo(Structure):
    _fields_ = [('ageArray', POINTER(c_int32)),  # 0:未知; >0:年龄
                ('num', c_int32)  # 检测的人脸个数
                ]


# 性别信息
class ASF_GenderInfo(Structure):
    genderArray: List[int]
    num: int
    _fields_ = [('genderArray', POINTER(c_int32)),  # 0:男性; 1:女性; -1:未知
                ('num', c_int32)  # 检测的人脸个数
                ]


# 3D角度信息
class ASF_Face3DAngle(Structure):
    _fields_ = [('roll', POINTER(c_float)),  # 横滚角
                ('yaw', POINTER(c_float)),  # 偏航角
                ('pitch', POINTER(c_float)),  # 俯仰角
                ('status', POINTER(c_int32)),  # 0:正常; 非 0:异常
                ('num', c_int32)  # 检测的人脸个数
                ]


# 活体信息
class ASF_LivenessInfo(Structure):
    _fields_ = [('isLive', POINTER(c_int32)),  # 0:非真人； 1:真人；-1：不确定； -2:传入人脸数 > 1；-3: 人脸过小；-4: 角度过大；-5: 人脸超出边界
                ('num', c_int32)  # 检测的人脸个数
                ]


# 活体置信度
class ASF_LivenessThreshold(Structure):
    _fields_ = [('thresholdmodel_BGR', c_float),  # BGR活体检测阈值设置，默认值0.5
                ('thresholdmodel_IR', c_float)  # IR活体检测阈值设置，默认值0.7
                ]


# =========================================================枚举=========================================================
# 人脸检测模式枚举
class ASF_DetectMode(Enum):
    ASF_DETECT_MODE_VIDEO = 0x00000000  # Video模式，一般用于多帧连续检测
    ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF  # Image模式，一般用于静态图的单次检测


# 人脸检测方向(根据应用场景，推荐选择单一角度，检测效果更优，角度按逆时针方向。)
class ASF_OrientPriority(Enum):
    ASF_OP_0_ONLY = 0x1,  # 常规预览下正方向
    ASF_OP_90_ONLY = 0x2,  # 基于0°逆时针旋转90°的方向
    ASF_OP_270_ONLY = 0x3,  # 基于0°逆时针旋转270°的方向
    ASF_OP_180_ONLY = 0x4,  # 基于0°旋转180°的方向（逆时针、顺时针效果一样）
    ASF_OP_ALL_OUT = 0x5  # 全角度


# 检测到的人脸角度,角度按逆时针方向
class ASF_OrientCode(Enum):
    ASF_OC_0 = 0x1  # 0 度
    ASF_OC_90 = 0x2  # 90 度
    ASF_OC_270 = 0x3  # 270 度
    ASF_OC_180 = 0x4  # 180 度
    ASF_OC_30 = 0x5  # 30 度
    ASF_OC_60 = 0x6  # 60 度
    ASF_OC_120 = 0x7  # 120 度
    ASF_OC_150 = 0x8  # 150 度
    ASF_OC_210 = 0x9  # 210 度
    ASF_OC_240 = 0xa  # 240 度
    ASF_OC_300 = 0xb  # 300 度
    ASF_OC_330 = 0xc  # 330 度


# 人脸比对可选的模型
class ASF_CompareModel(Enum):
    ASF_LIFE_PHOTO = 0x1  # 用于生活照之间的特征比对，推荐阈值0.80
    ASF_ID_PHOTO = 0x2  # 用于证件照或生活照与证件照之间的特征比对，推荐阈值0.82


# 检测模型
class ASF_DetectModel(Enum):
    ASF_DETECT_MODEL_RGB = 0x1  # RGB图像检测模型
    # 预留扩展其他检测模型
